import 'package:json_annotation/json_annotation.dart';

/// int?,double?,String?,bool?字段转化器列表。将任意字段转化为需要的类型
const nullFieldConvertList = <JsonConverter>[
  DynamicToIntNull(),
  DynamicToDoubleNull(),
  DynamicToStringNull(),
  DynamicToBoolNull(),
];

/// dynamic 转 int，转化失败则返回0
class DynamicToInt extends JsonConverter<int, dynamic> {
  const DynamicToInt();

  @override
  int fromJson(dynamic json) {
    if (json == null) {
      return 0;
    }

    if (json is int) {
      return json;
    }

    if (json is double) {
      return json.toInt();
    }

    if (json is String) {
      return int.tryParse(json) ?? 0;
    }

    if (json is bool) {
      return json ? 1 : 0;
    }

    return 0;
  }

  @override
  dynamic toJson(int object) {
    return object.toString();
  }
}

/// dynamic 转 int?
class DynamicToIntNull extends JsonConverter<int?, dynamic> {
  const DynamicToIntNull();

  @override
  int? fromJson(dynamic json) {
    if (json == null) {
      return null;
    }

    if (json is int) {
      return json;
    }

    if (json is double) {
      return json.toInt();
    }

    if (json is String) {
      return int.tryParse(json);
    }

    if (json is bool) {
      return json ? 1 : 0;
    }

    return null;
  }

  @override
  dynamic toJson(int? object) {
    return object?.toString();
  }
}

/// dynamic 转 double,转化失败则返回0
class DynamicToDouble extends JsonConverter<double, dynamic> {
  const DynamicToDouble();

  @override
  double fromJson(dynamic json) {
    if (json == null) {
      return 0;
    }

    if (json is double) {
      return json;
    }

    if (json is int) {
      return json.toDouble();
    }

    if (json is String) {
      return double.tryParse(json) ?? 0;
    }

    if (json is bool) {
      return json ? 1 : 0;
    }

    return 0;
  }

  @override
  dynamic toJson(double object) {
    return object.toString();
  }
}

/// dynamic 转 double?
class DynamicToDoubleNull extends JsonConverter<double?, dynamic> {
  const DynamicToDoubleNull();

  @override
  double? fromJson(dynamic json) {
    if (json == null) {
      return null;
    }

    if (json is double) {
      return json;
    }

    if (json is int) {
      return json.toDouble();
    }

    if (json is String) {
      return double.tryParse(json);
    }

    if (json is bool) {
      return json ? 1 : 0;
    }

    return null;
  }

  @override
  dynamic toJson(double? object) {
    return object?.toString();
  }
}

/// dynamic 转 String，转化失败则返回""
class DynamicToString extends JsonConverter<String, dynamic> {
  const DynamicToString();

  @override
  String fromJson(dynamic json) {
    if (json == null) {
      return "";
    }

    if (json is String) {
      return json;
    }

    if (json is num) {
      return json.toString();
    }

    if (json is bool) {
      return json.toString();
    }

    return "";
  }

  @override
  dynamic toJson(String object) {
    return object;
  }
}

/// dynamic 转 String?
class DynamicToStringNull extends JsonConverter<String?, dynamic> {
  const DynamicToStringNull();

  @override
  String? fromJson(dynamic json) {
    if (json == null) {
      return null;
    }

    if (json is String) {
      return json;
    }

    if (json is num) {
      return json.toString();
    }

    if (json is bool) {
      return json.toString();
    }

    return null;
  }

  @override
  dynamic toJson(String? object) {
    return object?.toString();
  }
}

/// dynamic 转 bool，转化失败则返回false
class DynamicToBool extends JsonConverter<bool, dynamic> {
  const DynamicToBool();

  @override
  bool fromJson(dynamic json) {
    if (json == null) {
      return false;
    }

    if (json is bool) {
      return json;
    }

    if (json is num) {
      return json > 0;
    }

    if (json is String) {
      if (json == "true") {
        return true;
      }

      var value = num.tryParse(json);
      if (value != null) {
        return value > 0;
      }
    }

    return false;
  }

  @override
  dynamic toJson(bool object) {
    return object ? 1 : 0;
  }
}

/// dynamic 转 bool?
class DynamicToBoolNull extends JsonConverter<bool?, dynamic> {
  const DynamicToBoolNull();

  @override
  bool? fromJson(dynamic json) {
    if (json == null) {
      return null;
    }

    if (json is bool) {
      return json;
    }

    if (json is num) {
      return json > 0;
    }

    if (json is String) {
      if (json == "true") {
        return true;
      }

      var value = num.tryParse(json);
      if (value != null) {
        return value > 0;
      }
    }

    return null;
  }

  @override
  dynamic toJson(bool? object) {
    return object != null && object ? 1 : 0;
  }
}
